Skip to content

fix: resolve Windows Bun virtual FS paths for Claude CLI subprocess#1091

Closed
coleam00 wants to merge 4 commits intodevfrom
archon/task-fix-issue-1087
Closed

fix: resolve Windows Bun virtual FS paths for Claude CLI subprocess#1091
coleam00 wants to merge 4 commits intodevfrom
archon/task-fix-issue-1087

Conversation

@coleam00
Copy link
Copy Markdown
Owner

Summary

  • On Windows, the Archon binary sets pathToClaudeCodeExecutable to a Bun virtual FS path (B:/~BUN/root/cli-xxx.js) that child processes cannot access, causing exit code 1 and "Module not found" errors
  • The SDK's extractFromBunfs utility only detects $bunfs (Linux/Mac) paths and silently passes Windows B:/~BUN/root/ paths through unchanged
  • Adds resolveWindowsBunfsCliPath() to packages/core/src/clients/claude.ts that detects Windows Bun FS paths by the ~BUN marker and extracts them to a real temp file using the same atomic write pattern as extractFromBunfs

Changes

  • packages/core/src/clients/claude.ts: Added resolveWindowsBunfsCliPath() function and resolvedCliPath constant; pathToClaudeCodeExecutable now uses resolvedCliPath instead of raw cliPath; updated embed import comment to document the Windows workaround
  • packages/core/src/clients/claude.test.ts: Added tests for resolveWindowsBunfsCliPath covering pass-through for non-Windows paths, Windows path extraction, and fallback behavior on extraction failure

Validation

All checks passed on first run:

Check Result
bun run type-check ✅ 0 errors (all 9 packages)
bun run lint ✅ 0 errors, 0 warnings
bun run format:check
bun run test ✅ 58+ tests passed, 0 failed

Root Cause

The Archon binary cross-compiles on Linux for Windows (--target bun-windows-x64). At compile time, import cliPath from '@anthropic-ai/claude-agent-sdk/embed' embeds cli.js into the binary's virtual FS. On Linux/Mac binaries the embedded path format is $bunfs/...; on Windows binaries the format is B:/~BUN/root/.... The SDK's extractFromBunfs.js hardcodes a $bunfs check and returns Windows virtual FS paths unchanged — child processes then fail to find the module since they cannot access the parent's virtual FS.

Fixes #1087

…1087)

On Windows, the compiled Archon binary embeds cli.js at B:/~BUN/root/
instead of $bunfs/. The SDK's extractFromBunfs only detects $bunfs paths,
so Windows paths pass through unchanged — child processes can't access the
parent's virtual FS, causing "Module not found" exit code 1.

Changes:
- Add resolveWindowsBunfsCliPath() to extract ~BUN paths to real temp files
- Use resolvedCliPath instead of raw cliPath for pathToClaudeCodeExecutable
- Add tests for path detection, extraction, and fallback behavior

Fixes #1087

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 17691ff9-2b0f-4f18-ac75-6c1ad15c9e38

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch archon/task-fix-issue-1087

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coleam00
Copy link
Copy Markdown
Owner Author

🔍 Comprehensive PR Review

PR: #1091 — fix: resolve Windows Bun virtual FS paths for Claude CLI subprocess
Reviewed by: 4 specialized agents (code-review, error-handling, test-coverage, comment-quality)
Date: 2026-04-11


Summary

This is a well-implemented, focused Windows compatibility fix that mirrors the upstream SDK logic faithfully. The implementation is correct, all 4 logical branches are tested, and scope discipline is excellent (zero unrelated changes). No critical or high-severity issues were found. Two quick MEDIUM fixes are recommended before marking ready.

Verdict: APPROVE (2 quick MEDIUM fixes recommended)

Severity Count
🔴 CRITICAL 0
🟠 HIGH 0
🟡 MEDIUM 2
🟢 LOW 5

🟡 Medium Issues (Recommend Fixing — Quick Wins)

1. console.warn message names the wrong virtual-FS prefix

📍 packages/core/src/clients/claude.ts:84

The warning says "Windows $bunfs" but $bunfs is the Linux/macOS prefix. The Windows prefix is ~BUN (what the guard on line 65 actually checks). A developer triaging a failed Claude subprocess on Windows will search for $bunfs, find the Linux/macOS code path, and investigate the wrong place.

View fix
// Current (misleading):
`[archon] Failed to extract Claude CLI from Windows $bunfs: ${(err as Error).message}. ...`

// Fixed:
`[archon] Failed to extract Claude CLI from Windows ~BUN virtual FS: ${(err as Error).message}. ...`

2. console.warn instead of structured Pino logger

📍 packages/core/src/clients/claude.ts:83-85

The rest of claude.ts uses the lazy-initialized getLog() structured logger throughout. The console.warn here bypasses Pino's log-level filtering and loses structured context (err, embeddedPath). The lazy getLog() pattern already exists in this file to allow safe calls before test mocks initialize — it's safe to use here.

View fix (also resolves Issue 1)
} catch (err) {
  // Log warning but fall back to original path — will fail but that was the
  // pre-fix behavior. Fail-open here since we can't throw at module init time.
  getLog().warn(
    { err, embeddedPath },
    'claude.windows_bunfs_extraction_failed'
  );
  return embeddedPath;
}

Switching to getLog().warn(...) resolves both MEDIUM issues — the structured event name and context are unambiguous.


🟢 Low Issues

View 5 low-priority suggestions
Issue Location Agent Suggestion
Node built-in imports placed after project imports claude.ts:46-49 code-review Move fs, path, os, crypto to top of import block (before SDK/@archon imports)
Test uses require() (CJS) instead of ESM import claude.test.ts:1124-1126 code-review Add top-level ESM import for fs, os, path at file top
(err as Error).message loses stack trace claude.ts:84 error-handling Pass full err object; if keeping console.warn, use String(err) defensively
No assertion that console.warn fires in fallback test claude.test.ts test-coverage Add spyOn(console, 'warn') assertion for regression-proofing the diagnostic
Inline guard comment slightly overstates extractFromBunfs guarantee claude.ts:62-64 comment-quality Change "are already resolved" → "are expected to have been resolved already"

✅ What's Good

  • Mirrors upstream SDK faithfully — implementation is nearly identical to extractFromBunfs.js, minimizing divergence risk and making intent immediately clear to reviewers
  • Atomic write patternwriteFileSyncchmodSyncrenameSync prevents partial-read races, same as upstream
  • Content-hash temp dir — reuses the same extracted file for the same binary version, no temp file accumulation across restarts
  • All 4 branches tested — pass-through (non-Windows), $bunfs pass-through, successful extraction with content integrity verified, and error fallback
  • Real FS tests are justified — Bun's module binding means spyOn(fs, 'readFileSync') can't intercept named imports; real FS tests are more reliable here (documented in scope)
  • Fallback is intentional and documented — catch block comment explains why throwing is impossible at module init time, matching CLAUDE.md's requirement to document intentional fail-open
  • Correct test batching — no new mock.module() calls; slots into existing claude.test.ts batch without package.json changes

📋 Suggested Follow-up Issues

Issue Title Priority
Add console.warn assertion to Windows bunfs fallback test P3
Normalize import ordering in claude.ts P3

Next Steps

  1. ⚡ Fix the 2 MEDIUM issues (ideally by switching console.warngetLog().warn(...) which resolves both)
  2. 📝 LOW issues are optional — consider deferring to follow-up
  3. 🎯 Mark ready and merge when CI is green

Reviewed by Archon comprehensive-pr-review workflow
Artifacts: ~/.archon/workspaces/coleam00/Archon/artifacts/runs/cca84316788e97e0481c92609c58fad2/review/

- Move Node built-in imports (fs, path, os, crypto) before SDK/project imports
- Switch console.warn to getLog().warn() with structured context and correct
  event name (claude.windows_bunfs_extraction_failed), fixing the wrong $bunfs
  label in the warning message and aligning with project Pino logging conventions
- Soften inline guard comment: "are already resolved" -> "are expected to have
  been resolved already" to avoid overstating the extractFromBunfs guarantee
- Add module-level comment for resolvedCliPath explaining the once-at-init pattern
- Replace require() CJS calls in test with top-level ESM imports (fs, os, path)
- Add assertion in fallback test that mockLogger.warn fires with the correct
  event name, regression-proofing the diagnostic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coleam00
Copy link
Copy Markdown
Owner Author

Fix Report: PR #1091

Date: 2026-04-11T00:00:00Z
Status: COMPLETE
Commit: 42f322c
Philosophy: Aggressive fix — lean towards fixing everything


Summary

All 7 review findings were addressed (2 MEDIUM + 5 LOW). The primary fix switches the catch block from console.warn to getLog().warn() with structured context and a correct event name, which simultaneously resolves the wrong virtual-FS prefix label ($bunfs → event name claude.windows_bunfs_extraction_failed) and the logging inconsistency. Additional polish fixes cover import ordering, comment accuracy, a new module-level constant comment, and ESM-style test imports with a logger-assertion in the fallback test.


Fixes Applied

Severity Finding Location What Was Done
MEDIUM console.warn uses wrong virtual-FS prefix ($bunfs instead of ~BUN) claude.ts:84 Switched to getLog().warn({ err, embeddedPath }, 'claude.windows_bunfs_extraction_failed') — event name is unambiguous and prefix-correct
MEDIUM console.warn instead of structured Pino logger claude.ts:83-85 Same fix as above — getLog().warn() with structured { err, embeddedPath } context
LOW Node built-in imports placed after project imports claude.ts:46-49 Moved fs, path, os, crypto imports to top of file (before SDK and @archon/* imports)
LOW Inline guard comment overstates extractFromBunfs guarantee claude.ts:62-64 Changed "are already resolved" to "are expected to have been resolved already"
LOW resolvedCliPath constant has no comment claude.ts:90 Added one-liner explaining once-at-init-time caching rationale
LOW Test uses require() (CJS) instead of ESM imports claude.test.ts:1124-1126 Added top-level import { mkdirSync, writeFileSync, readFileSync, rmSync } from 'fs' etc.; removed inline require() calls
LOW No assertion that logger fires on fallback claude.test.ts:1147 Added mockLogger.warn call count and event name assertions in the fallback test

Validation

Check Status
Type check
Lint
Format
Tests ✅ all 9 packages passed (0 failures)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coleam00
Copy link
Copy Markdown
Owner Author

Archon PR Validation Report

Verdict: REQUEST_CHANGES

Summary

The fix correctly solves the Windows Bun virtual FS path issue with a clean, minimal approach mirroring the SDK's own extraction pattern. One blocking issue: a Temporal Dead Zone (TDZ) ordering bug would crash the module on Windows when extraction fails. Simple fix — reorder declarations.

Bug Confirmation

Claim Main Feature
pathToClaudeCodeExecutable passes raw virtual FS path Confirmed Fixed — uses resolvedCliPath
No Windows virtual FS handling exists Confirmed Fixed — resolveWindowsBunfsCliPath() added
SDK only handles $bunfs paths Confirmed Worked around

Issues

Must fix (HIGH): const resolvedCliPath = resolveWindowsBunfsCliPath(cliPath) is initialized BEFORE cachedLog/getLog() are declared. If extraction fails, getLog() hits a TDZ → ReferenceError crash instead of graceful fallback. Fix: move resolvedCliPath init after getLog() declaration.

Nice to have (LOW): Add existsSync check to skip re-extraction when temp file already exists (matches SDK pattern).

What's Done Well

  • Mirrors SDK's atomic-write extraction pattern
  • Hash-based idempotent temp paths
  • Well-structured tests with cleanup
  • Minimal, narrowly scoped change

Validated by archon-validate-pr workflow

…indows

When extraction fails, getLog() was called before its declaration,
causing a ReferenceError. Found by validate-pr workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wirasm added a commit that referenced this pull request Apr 14, 2026
…esolver

Drop `@anthropic-ai/claude-agent-sdk/embed` and resolve Claude Code via
CLAUDE_BIN_PATH env → assistants.claude.claudeBinaryPath config → throw
with install instructions. The embed's silent failure modes on macOS
(#1210) and Windows (#1087) become actionable errors with a documented
recovery path.

Dev mode (bun run) remains auto-resolved via node_modules. The setup
wizard auto-detects Claude Code by probing the native installer path
(~/.local/bin/claude), npm global cli.js, and PATH, then writes
CLAUDE_BIN_PATH to ~/.archon/.env. Dockerfile pre-sets CLAUDE_BIN_PATH
so extenders using the compiled binary keep working. Release workflow
gets negative and positive resolver smoke tests.

Docs, CHANGELOG, README, .env.example, CLAUDE.md, test-release and
archon skills all updated to reflect the curl-first install story.

Retires #1210, #1087, #1091 (never merged, now obsolete).
Implements #1176.
@Wirasm
Copy link
Copy Markdown
Collaborator

Wirasm commented Apr 14, 2026

Filing context: #1217 is landing as a different approach to the same class of bug this draft targets.

Instead of extracting cli.js from Windows ~BUN virtual FS, #1217 drops the SDK embed entirely (import cliPath from '@anthropic-ai/claude-agent-sdk/embed') and requires compiled-binary users to point Archon at their Claude Code install via CLAUDE_BIN_PATH env or assistants.claude.claudeBinaryPath config. That closes off all platform-specific extraction code paths in one shot — Windows ~BUN, macOS /Users/runner/…, and any future Bun bundler quirks — and also implements #1176 (the user-facing override option).

The net effect is that #1217 fixes #1087 (which this draft was targeting) and #1210 (the macOS manifestation that surfaced after this draft) without needing the Windows-only extractor.

Leaving this PR open for you to close at your convenience — not trying to auto-close on merge.

Wirasm added a commit that referenced this pull request Apr 14, 2026
…solver (#1217)

* feat(providers): replace Claude SDK embed with explicit binary-path resolver

Drop `@anthropic-ai/claude-agent-sdk/embed` and resolve Claude Code via
CLAUDE_BIN_PATH env → assistants.claude.claudeBinaryPath config → throw
with install instructions. The embed's silent failure modes on macOS
(#1210) and Windows (#1087) become actionable errors with a documented
recovery path.

Dev mode (bun run) remains auto-resolved via node_modules. The setup
wizard auto-detects Claude Code by probing the native installer path
(~/.local/bin/claude), npm global cli.js, and PATH, then writes
CLAUDE_BIN_PATH to ~/.archon/.env. Dockerfile pre-sets CLAUDE_BIN_PATH
so extenders using the compiled binary keep working. Release workflow
gets negative and positive resolver smoke tests.

Docs, CHANGELOG, README, .env.example, CLAUDE.md, test-release and
archon skills all updated to reflect the curl-first install story.

Retires #1210, #1087, #1091 (never merged, now obsolete).
Implements #1176.

* fix(providers): only pass --no-env-file when spawning Claude via Bun/Node

`--no-env-file` is a Bun flag that prevents Bun from auto-loading
`.env` from the subprocess cwd. It is only meaningful when the Claude
Code executable is a `cli.js` file — in which case the SDK spawns it
via `bun`/`node` and the flag reaches the runtime.

When `CLAUDE_BIN_PATH` points at a native compiled Claude binary (e.g.
`~/.local/bin/claude` from the curl installer, which is Anthropic's
recommended default), the SDK executes the binary directly. Passing
`--no-env-file` then goes straight to the native binary, which
rejects it with `error: unknown option '--no-env-file'` and the
subprocess exits code 1.

Emit `executableArgs` only when the target is a `.js` file (dev mode
or explicit cli.js path). Caught by end-to-end smoke testing against
the curl-installed native Claude binary.

* docs: record env-leak validation result in provider comment

Verified end-to-end with sentinel `.env` and `.env.local` files in a
workflow CWD that the native Claude binary (curl installer) does not
auto-load `.env` files. With Archon's full spawn pathway and parent
env stripped, the subprocess saw both sentinels as UNSET. The
first-layer protection in `@archon/paths` (#1067) handles the
inheritance leak; `--no-env-file` only matters for the Bun-spawned
cli.js path, where it is still emitted.

* chore(providers): cleanup pass — exports, docs, troubleshooting

Final-sweep cleanup tied to the binary-resolver PR:

- Mirror Codex's package surface for the new Claude resolver: add
  `./claude/binary-resolver` subpath export and re-export
  `resolveClaudeBinaryPath` + `claudeFileExists` from the package
  index. Renames the previously single `fileExists` re-export to
  `codexFileExists` for symmetry; nothing outside the providers
  package was importing it.
- Add a "Claude Code not found" entry to the troubleshooting reference
  doc with platform-specific install snippets and pointers to the
  AI Assistants binary-path section.
- Reframe the example claudeBinaryPath in reference/configuration.md
  away from cli.js-only language; it accepts either the native binary
  or cli.js.

* test+refactor(providers, cli): address PR review feedback

Two test gaps and one doc nit from the PR review (#1217):

- Extract the `--no-env-file` decision into a pure exported helper
  `shouldPassNoEnvFile(cliPath)` so the native-binary branch is unit
  testable without mocking `BUNDLED_IS_BINARY` or running the full
  sendQuery pathway. Six new tests cover undefined, cli.js, native
  binary (Linux + Windows), Homebrew symlink, and suffix-only matching.
  Also adds a `claude.subprocess_env_file_flag` debug log so the
  security-adjacent decision is auditable.

- Extract the three install-location probes in setup.ts into exported
  wrappers (`probeFileExists`, `probeNpmRoot`, `probeWhichClaude`) and
  export `detectClaudeExecutablePath` itself, so the probe order can be
  spied on. Six new tests cover each tier winning, fall-through
  ordering, npm-tier skip when not installed, and the
  which-resolved-but-stale-path edge case.

- CLAUDE.md `claudeBinaryPath` placeholder updated to reflect that the
  field accepts either the native binary or cli.js (the example value
  was previously `/absolute/path/to/cli.js`, slightly misleading now
  that the curl-installer native binary is the default).

Skipped from the review by deliberate scope decision:

- `resolveClaudeBinaryPath` async-with-no-await: matches Codex's
  resolver signature exactly. Changing only Claude breaks symmetry;
  if pursued, do both providers in a separate cleanup PR.
- `isAbsolute()` validation in parseClaudeConfig: Codex doesn't do it
  either. Resolver throws on non-existence already.
- Atomic `.env` writes in setup wizard: pre-existing pattern this PR
  touched only adjacently. File as separate issue if needed.
- classifyError branch in dag-executor for setup errors: scope creep.
- `.env.example` "missing #" claim: false positive (verified all
  CLAUDE_BIN_PATH lines have proper comment prefixes).

* fix(test): use path.join in Windows-compatible probe-order test

The "tier 2 wins (npm cli.js)" test hardcoded forward-slash path
comparisons, but `path.join` produces backslashes on Windows. Caused
the Windows CI leg of the test suite to fail while macOS and Linux
passed. Use `path.join` for both the mock return value and the
expectation so the separator matches whatever the platform produces.
@coleam00
Copy link
Copy Markdown
Owner Author

Closing — the underlying bug was real (#1087), but PR #1217 (merged April 14) already resolved this with a better approach: it removed the embed import entirely and switched to binary-resolver.ts which requires compiled-binary users to point to their own Claude Code installation via CLAUDE_BIN_PATH or assistants.claude.claudeBinaryPath.

Since there's no remaining code path using import cliPath from '@anthropic-ai/claude-agent-sdk/embed', the Windows virtual FS extraction workaround in this PR is no longer needed. The file it targets (packages/core/src/clients/claude.ts) has also been moved to packages/providers/src/claude/provider.ts.

Thanks for the solid investigation and fix — the approach was correct, just superseded by #1217.

@coleam00 coleam00 closed this Apr 16, 2026
joaobmonteiro pushed a commit to joaobmonteiro/Archon that referenced this pull request Apr 26, 2026
…solver (coleam00#1217)

* feat(providers): replace Claude SDK embed with explicit binary-path resolver

Drop `@anthropic-ai/claude-agent-sdk/embed` and resolve Claude Code via
CLAUDE_BIN_PATH env → assistants.claude.claudeBinaryPath config → throw
with install instructions. The embed's silent failure modes on macOS
(coleam00#1210) and Windows (coleam00#1087) become actionable errors with a documented
recovery path.

Dev mode (bun run) remains auto-resolved via node_modules. The setup
wizard auto-detects Claude Code by probing the native installer path
(~/.local/bin/claude), npm global cli.js, and PATH, then writes
CLAUDE_BIN_PATH to ~/.archon/.env. Dockerfile pre-sets CLAUDE_BIN_PATH
so extenders using the compiled binary keep working. Release workflow
gets negative and positive resolver smoke tests.

Docs, CHANGELOG, README, .env.example, CLAUDE.md, test-release and
archon skills all updated to reflect the curl-first install story.

Retires coleam00#1210, coleam00#1087, coleam00#1091 (never merged, now obsolete).
Implements coleam00#1176.

* fix(providers): only pass --no-env-file when spawning Claude via Bun/Node

`--no-env-file` is a Bun flag that prevents Bun from auto-loading
`.env` from the subprocess cwd. It is only meaningful when the Claude
Code executable is a `cli.js` file — in which case the SDK spawns it
via `bun`/`node` and the flag reaches the runtime.

When `CLAUDE_BIN_PATH` points at a native compiled Claude binary (e.g.
`~/.local/bin/claude` from the curl installer, which is Anthropic's
recommended default), the SDK executes the binary directly. Passing
`--no-env-file` then goes straight to the native binary, which
rejects it with `error: unknown option '--no-env-file'` and the
subprocess exits code 1.

Emit `executableArgs` only when the target is a `.js` file (dev mode
or explicit cli.js path). Caught by end-to-end smoke testing against
the curl-installed native Claude binary.

* docs: record env-leak validation result in provider comment

Verified end-to-end with sentinel `.env` and `.env.local` files in a
workflow CWD that the native Claude binary (curl installer) does not
auto-load `.env` files. With Archon's full spawn pathway and parent
env stripped, the subprocess saw both sentinels as UNSET. The
first-layer protection in `@archon/paths` (coleam00#1067) handles the
inheritance leak; `--no-env-file` only matters for the Bun-spawned
cli.js path, where it is still emitted.

* chore(providers): cleanup pass — exports, docs, troubleshooting

Final-sweep cleanup tied to the binary-resolver PR:

- Mirror Codex's package surface for the new Claude resolver: add
  `./claude/binary-resolver` subpath export and re-export
  `resolveClaudeBinaryPath` + `claudeFileExists` from the package
  index. Renames the previously single `fileExists` re-export to
  `codexFileExists` for symmetry; nothing outside the providers
  package was importing it.
- Add a "Claude Code not found" entry to the troubleshooting reference
  doc with platform-specific install snippets and pointers to the
  AI Assistants binary-path section.
- Reframe the example claudeBinaryPath in reference/configuration.md
  away from cli.js-only language; it accepts either the native binary
  or cli.js.

* test+refactor(providers, cli): address PR review feedback

Two test gaps and one doc nit from the PR review (coleam00#1217):

- Extract the `--no-env-file` decision into a pure exported helper
  `shouldPassNoEnvFile(cliPath)` so the native-binary branch is unit
  testable without mocking `BUNDLED_IS_BINARY` or running the full
  sendQuery pathway. Six new tests cover undefined, cli.js, native
  binary (Linux + Windows), Homebrew symlink, and suffix-only matching.
  Also adds a `claude.subprocess_env_file_flag` debug log so the
  security-adjacent decision is auditable.

- Extract the three install-location probes in setup.ts into exported
  wrappers (`probeFileExists`, `probeNpmRoot`, `probeWhichClaude`) and
  export `detectClaudeExecutablePath` itself, so the probe order can be
  spied on. Six new tests cover each tier winning, fall-through
  ordering, npm-tier skip when not installed, and the
  which-resolved-but-stale-path edge case.

- CLAUDE.md `claudeBinaryPath` placeholder updated to reflect that the
  field accepts either the native binary or cli.js (the example value
  was previously `/absolute/path/to/cli.js`, slightly misleading now
  that the curl-installer native binary is the default).

Skipped from the review by deliberate scope decision:

- `resolveClaudeBinaryPath` async-with-no-await: matches Codex's
  resolver signature exactly. Changing only Claude breaks symmetry;
  if pursued, do both providers in a separate cleanup PR.
- `isAbsolute()` validation in parseClaudeConfig: Codex doesn't do it
  either. Resolver throws on non-existence already.
- Atomic `.env` writes in setup wizard: pre-existing pattern this PR
  touched only adjacently. File as separate issue if needed.
- classifyError branch in dag-executor for setup errors: scope creep.
- `.env.example` "missing #" claim: false positive (verified all
  CLAUDE_BIN_PATH lines have proper comment prefixes).

* fix(test): use path.join in Windows-compatible probe-order test

The "tier 2 wins (npm cli.js)" test hardcoded forward-slash path
comparisons, but `path.join` produces backslashes on Windows. Caused
the Windows CI leg of the test suite to fail while macOS and Linux
passed. Use `path.join` for both the mock return value and the
expectation so the separator matches whatever the platform produces.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Claude Code process exited with code 1 via webui

2 participants